import Phaser from "phaser";
import LinkSearch from './Connectivity'
import {base64ToBlob} from './util'

import bg from './assets/image/bg-col.jpg';
import text from './assets/image/Match and connect.png';
import img1 from './assets/image/1.png';
import img2 from './assets/image/2.png';
import img3 from './assets/image/3.png';
import img4 from './assets/image/4.png';
import img5 from './assets/image/5.png';
import img6 from './assets/image/6.png';
import img7 from './assets/image/7.png';
import rect from './assets/image/round-rect.png';
import checkbox from './assets/image/checkbox.png';
import icon from './assets/image/icon.png';
import logo from './assets/image/logo.png';
import download from './assets/image/download.png';
import line from './assets/image/line.png';
import flower from './assets/image/flower.png';
import finger from './assets/image/hand.png'

import audio1 from './assets/audio/click.mp3';
import audio2 from './assets/audio/linked.mp3';

const audio1BlobURL = URL.createObjectURL(base64ToBlob(audio1))
const audio2BlobURL = URL.createObjectURL(base64ToBlob(audio2))

const config = {
  type: Phaser.AUTO,
  parent: "phaser-example",
  width: document.body.clientWidth,
  height: document.body.clientHeight,
  scene: {preload, create}
};

setTimeout(() => {
  document.querySelector(".loadBox").remove()
}, 600)
setTimeout(() => {
  const game = new Phaser.Game(config);
}, 500)

const images = {
  bg,
  text,
  img1,
  img2,
  img3,
  img4,
  img5,
  img6,
  img7,
  rect,
  checkbox,
  icon,
  logo,
  download,
  line,
  flower,
  finger
};

const proportion = config.width / config.height;
// 棋盘布局
const colLayout = [
  [1, 2, 3, 2, 4],
  [5, 3, 6, 5, 1],
  [4, 1, 7, 7, 4],
  [6, 5, 3, 6, 2],
  [2, 3, 4, 5, 6],
  [1, 6, 1, 4, 2],
  [3, 4, 5, 2, 3],
  [7, 6, 7, 1, 5]
]
const rowLayout = [
  [1, 2, 3, 2, 4, 3, 2, 6, 2, 7],
  [5, 3, 6, 5, 1, 7, 7, 4, 6, 3],
  [4, 1, 4, 7, 4, 1, 6, 1, 4, 2],
  [6, 5, 3, 6, 2, 3, 4, 5, 2, 3],
  [2, 3, 4, 5, 6, 7, 6, 7, 1, 5]
]
// 手指位置
const colPos = [{i: 2, j: 2}, {i: 2, j: 3}];
const rowPos = [{i: 1, j: 5}, {i: 1, j: 6}];
// 游戏进度
let gameStep = 1;
// image
let topText;
// audio
let clickAudio, linkedAudio;

function preload() {
  layoutInit(colLayout);
  layoutInit(rowLayout);

  // 监听创建游戏中的元素（背景图、logo等）加载完成后再创建
  this.textures.on(Phaser.Textures.Events.LOAD, key => {
    // 加载完成，开始处理游戏图像
    if (key === 'finger') {
      // 背景
      const background = createBackground(this);

      // 顶部文字
      topText = createTopText(this);

      const checkerboard = createCheckerboard(this);

      const container = proportion <= 0.76
        ? createPiece(this, checkerboard, 8, 5)
        : createPiece(this, checkerboard, 5, 10);

      const finger = createFinger(this, container);
      fingerAnimation(this, finger);

      // 监听点击事件
      clickHandle(this, container, finger);
    }
  }, this);

  const keys = Object.keys(images);

  // 直接加载base64会失败（this.load.image）
  keys.forEach(key => {
    this.textures.addBase64(key, images[key]);
  });

  this.load.audio('click', audio1BlobURL);
  this.load.audio('linked', audio2BlobURL);
}

function create() {
  clickAudio = this.sound.add('click');
  linkedAudio = this.sound.add('linked')

  this.input.on(Phaser.Input.Events.POINTER_UP, installHandle)
}

/**
 * 初始化棋盘布局数组，边缘填充0
 * @param {[][]} layout 被填充的数组
 */
const layoutInit = layout => {
  layout.push(Array(layout[0].length).fill(0))
  layout.unshift(Array(layout[0].length).fill(0))
  layout.forEach(row => {
    row.push(0);
    row.unshift(0);
  })
}

/**
 * 创建背景
 * @param {Phaser.Scene} that
 * @return {Phaser.GameObjects.Image}
 */
const createBackground = that => {
  const bg = that.add.image(config.width / 2, config.height / 2, 'bg');
  bg.scale = Math.max(config.width / bg.displayWidth, config.height / bg.displayHeight);

  return bg;
}


/**
 * 创建顶部文字
 * @param {Phaser.Scene} that
 * @return {Phaser.GameObjects.Image}
 */
const createTopText = that => {
  return that.add.image(config.width / 2, config.height / 2, 'text');
}


/**
 * 创建棋盘
 * @param {Phaser.Scene} that
 * @return {Phaser.GameObjects.Image}
 */
const createCheckerboard = (that) => {
  let width;
  let height;

  // 这是一坨shit，请不要动
  proportion <= 0.76
    ? proportion <= 0.5
    ? height = (width = config.width * 0.85) * 8 / 5
    : width = (height = config.height * 0.75) * 5 / 8
    : proportion <= 1.6
    ? height = (width = config.width * 0.85) * 5 / 10
    : width = (height = config.height * 0.75) * 10 / 5

  /**
   * 使用一个不存在的图片
   * @type {Phaser.GameObjects.Image}
   */
  let checkerboard = that.add.image(config.width / 2, config.height / 2, 'non');
  checkerboard.scaleX = width / checkerboard.displayWidth;
  checkerboard.scaleY = height / checkerboard.displayHeight;
  checkerboard.visible = false;

  // 对文字和棋盘进行重新布局
  // @change 2020.08.18 横板文字缩小
  topText.scale = (proportion > 0.76 ? checkerboard.displayWidth * 0.8 : width) / topText.displayWidth;
  // 拿手算y坐标
  topText.y = (config.height - height - topText.displayHeight / 2) / 2;
  checkerboard.y += topText.displayHeight / 2;

  // @add 2020.08.18 竖版图块整体往下移一点，下方留一个图块宽的距离，上方文案在空白处居中。
  if (proportion <= 0.76) {
    checkerboard.y = config.height - checkerboard.displayHeight * 0.625;
    topText.y = (config.height - checkerboard.displayHeight * 1.125) / 2;
  }

  return checkerboard;
}

/**
 * 创建底部圆角矩形、棋子、选中框
 * @param {Phaser.Scene} that
 * @param {Phaser.GameObjects.Image} checkerboard 棋盘
 * @param {number} row 行计数
 * @param {number} col 列计数
 * @return {{checkboxes: [], lows: [][], els: [][]}}
 */
const createPiece = (that, checkerboard, row, col) => {
  const container = {
    checkboxes: [],
    lows: [],
    els: []
  }

  const width = checkerboard.displayWidth / col;
  const startX = checkerboard.x - checkerboard.displayWidth / 2 + width / 2;
  const startY = checkerboard.y - checkerboard.displayHeight / 2 + width / 2;

  const layout = proportion <= 0.76 ? colLayout : rowLayout;

  // 创建棋子和底部圆角矩形
  for (let i = 0; i < row; i++) {
    container.lows.push([]);
    container.els.push([]);
    for (let j = 0; j < col; j++) {
      // 底部圆角矩形
      const low = that.add.image(startX + width * j, startY + width * i, 'rect');

      // 棋子
      const el = that.add.image(startX + width * j, startY + width * i, `img${layout[i + 1][j + 1]}`);
      container.lows[i].push(low);
      container.els[i].push(el);
      // 调整大小
      low.scale = width / low.displayWidth;
      el.scale = width * 0.76 / el.displayWidth;

      // 存储下标，方便查找
      low.i = el.i = i;
      low.j = el.j = j;

      low._y = low.y;
    }
  }

  // 创建2个选中框
  for (let i = 0; i < 2; i++) {
    const checkbox = that.add.image(startX, startY, 'checkbox');
    container.checkboxes.push(checkbox);
    checkbox.setOrigin(0.53, 0.53);
    checkbox.scale = width * 1.1 / checkbox.width;
    checkbox.visible = false;
  }

  return container;
}

/**
 * 创建手指
 * @param {Phaser.Scene} that
 * @param {{checkboxes: [], lows: [][], els: [][]}} container
 * @return {Phaser.GameObjects.Image}
 */
const createFinger = (that, container) => {
  const pos = proportion <= 0.76 ? colPos : rowPos;
  const els = container.els[pos[0].i][pos[0].j];
  const finger = that.add.image(els.x, els.y, 'finger');
  finger.setOrigin(0, 0);
  finger.scale = container.checkboxes[0].displayWidth * 1.5 / finger.displayWidth;
  finger.nextPosIndex = container.els[pos[1].i][pos[1].j];

  return finger;
}

/**
 * 手指动画
 * @param {Phaser.Scene} that
 * @param {Phaser.GameObjects.Image} finger
 */
const fingerAnimation = (that, finger) => {
  that.tweens.add({
    targets: finger,
    scale: finger.scale - 0.1,
    duration: 600,
    ease: Phaser.Math.Easing.Sine.InOut,
    // 反向运动，yoyo?
    yoyo: true,
    loop: -1
  })
}

/**
 * 点击事件
 * @param {Phaser.Scene} that
 * @param {{checkboxes: [], lows: [][], els: [][]}} container
 * @param {Phaser.GameObjects.Image} finger
 */
let isClick = true;
let linkCount = 0;
const clickHandle = (that, container, finger) => {
  let pre = null;
  that.input.on(Phaser.Input.Events.POINTER_UP, e => {
    // 防抖
    if (!isClick) return;
    // 知道isClick === true之前，点击事件是无效的

    isClick = false;

    // click position
    const {downX, downY} = e;
    const point = {x: downX, y: downY};

    // &: 新手指引的两个坐标必须是可以连接的，狗则出现bug概不负责
    // 新手指引进度: gameStep === 1 OR gameStep === 2
    // 进入正式游戏: gameStep === 3
    if (gameStep === 1) {
      pre = step1(that, container, point, finger)
    } else if (gameStep === 2) {
      step2(that, container, point, finger, pre)
    } else if (finger.alpha === 0 && gameStep === 3) {
      step3(that, container, pre, point)
    }
  })
}

/**
 * 新手引导1
 * @param {Phaser.Scene} that
 * @param {{checkboxes: [], lows: [][], els: [][]}} container
 * @param {{x:number, y:number}} point
 * @param {Phaser.GameObjects.Image} finger
 * @return {{}|{piece: Phaser.GameObjects.Image, rect: Phaser.GameObjects.Image}}
 */
const step1 = (that, container, point, finger) => {
  // 新手引导步骤1成功否
  const isNext = checkboxActive(container, point, 0);

  // 准备下一次点击
  if (isNext) {
    clickAudio.play()

    // 手指移动
    that.tweens.add({
      targets: finger,
      x: finger['nextPosIndex'].x,
      duration: 600,
      ease: Phaser.Math.Easing.Sine.InOut,
      onComplete: () => {
        gameStep++;
        isClick = true;
      }
    })
    // 存储点击方块
    const rect = findLow(container, 'lows', 0);
    const piece = findLow(container, 'els', 0);

    return {rect, piece}
  } else {
    isClick = true;
    return {}
  }
}

/**
 * 新手引导步骤2
 * @param {Phaser.Scene} that
 * @param {{checkboxes: [], lows: [][], els: [][]}} container
 * @param {{x:number, y:number}} point
 * @param {Phaser.GameObjects.Image} finger
 * @param {{piece: Phaser.GameObjects.Image, rect: Phaser.GameObjects.Image}|null} pre
 */
const step2 = (that, container, point, finger, pre) => {
  // 新手引导步骤2成功否
  const isNext = checkboxActive(container, point, 1);
  if (isNext) {
    const {rect, piece} = pre;
    const curRect = findLow(container, 'lows', 1);
    const curPiece = findLow(container, 'els', 1);

    // 方块连接: 这里假定两个选中块一定可以连接，否则可能会出现两个选中块不能连接而且选中状态不能解除
    const link = linkPiece(that, rect, curRect);
    if (link !== null) {
      linkedAudio.play()

      // 生成连接线
      createLink(that, rect, curRect, link);

      // 选中框隐藏
      checkboxHidden(that, container);
      // piece消除动画
      pieceDestroy(that, rect, curRect, piece, curPiece, () => {
        gameStep++;
        if (proportion <= 0.76) {
          colLayout[rect['i'] + 1][rect['j'] + 1] = 0
          colLayout[curRect['i'] + 1][curRect['j'] + 1] = 0
        } else {
          rowLayout[rect['i'] + 1][rect['j'] + 1] = 0
          rowLayout[curRect['i'] + 1][curRect['j'] + 1] = 0
        }
        // 棋子下落
        pieceDecline(that, container, rect);
        pieceDecline(that, container, curRect);

        rect.visible = piece.visible = curRect.visible = curPiece.visible = false;

        // 消除数加1
        linkCount++;
      });
    }

    // 手指消失
    that.tweens.add({
      targets: finger,
      alpha: 0,
      duration: 300,
      ease: Phaser.Math.Easing.Sine.InOut,
      onComplete: () => {
        finger.destroy();
      }
    })
  } else {
    isClick = true
  }
}

/**
 * 新手引导：查找圆角矩形底部方块
 * @param {{checkboxes: [], lows: [][], els: [][]}} container
 * @param {string} target
 * @param {number} index
 * @return {Phaser.GameObjects.Image}
 */
const findLow = (container, target, index) => {
  return proportion <= 0.76
    ? container[target][colPos[index].i][colPos[index].j]
    : container[target][rowPos[index].i][rowPos[index].j];
}

/**
 * 新手引导结束
 * @param {Phaser.Scene} that
 * @param {{checkboxes: Phaser.GameObjects.Image[], lows: [][], els: [][]}} container
 * @param {{piece: Phaser.GameObjects.Image, rect: Phaser.GameObjects.Image}|null} pre
 * @param {{x:number, y:number}} point 当前点击
 */
const step3 = (that, container, pre, point) => {
  // 当前点击的棋子
  const click = findRect(container, point);

  if (click === null || click.piece === pre.piece) {
    isClick = true;
    if (click !== null) {
      clickAudio.play()
    }
    console.log('两次点击相同')
    return;
  }

  // 判断pre和当前点击是否可连接
  let link = linkPiece(that, pre.rect, click.rect);
  let checkbox;
  // 上次点击是空，表示已经消除，需要给pre赋值当前点击 OR 不可连接则赋值pre为当前点击
  if (pre.rect === null || link === null) {
    checkbox = container.checkboxes[0];
    pre.rect = click.rect;
    pre.piece = click.piece;
    clickAudio.play();
    console.log('上次点击是空OR已消除')
    isClick = true;
  } else {
    linkedAudio.play()

    checkbox = container.checkboxes[1];

    // 生成连接线
    createLink(that, pre.rect, click.rect, link);

    // 选中框隐藏
    checkboxHidden(that, container);

    // 消除
    pieceDestroy(that, pre.rect, click.rect, pre.piece, click.piece, () => {
      if (proportion <= 0.76) {
        colLayout[pre.rect['i'] + 1][pre.rect['j'] + 1] = 0
        colLayout[click.rect['i'] + 1][click.rect['j'] + 1] = 0
      } else {
        rowLayout[pre.rect['i'] + 1][pre.rect['j'] + 1] = 0
        rowLayout[click.rect['i'] + 1][click.rect['j'] + 1] = 0
      }

      // 棋子下落
      pieceDecline(that, container, pre.rect);
      pieceDecline(that, container, click.rect);

      click.rect.visible = click.piece.visible = pre.piece.visible = pre.rect.visible = false;

      // 计数
      linkCount++;

      if (proportion <= 0.76 && linkCount === 40 / 2 || proportion > 0.76 && linkCount === 50 / 2) {
        gameOver(that);
      }
    });
  }
  // 选中框显示
  checkbox.x = click.rect.x;
  checkbox.y = click.rect.y;
  checkbox.visible = true;
}

/**
 * 棋子下落
 * @param {Phaser.Scene} that
 * @param {{checkboxes: Phaser.GameObjects.Image[], lows: [][], els: [][]}} container
 * @param {Phaser.GameObjects.Image} image
 */
const pieceDecline = (that, container, image) => {
  if (image['i'] === 0) isClick = true

  for (let i = 0; i < image['i']; i++) {
    // 记录要到达的y坐标
    const y = container.lows[i + 1][image['j']]._y;

    container.lows[i][image['j']]._y = y;
    container.els[i][image['j']]._y = y;

    that.tweens.add({
      targets: [container.lows[i][image['j']], container.els[i][image['j']]],
      y,
      duration: 300,
      ease: Phaser.Math.Easing.Sine.InOut,
      onComplete() {
        isClick = true;
      }
    })
  }

  // 数组更新
  for (let i = image['i']; i > 0; i--) {
    if (proportion <= 0.76) {
      colLayout[i + 1][image['j'] + 1] = colLayout[i][image['j'] + 1];
      colLayout[i][image['j'] + 1] = 0;
    } else {
      rowLayout[i + 1][image['j'] + 1] = rowLayout[i][image['j'] + 1];
      rowLayout[i][image['j'] + 1] = 0;
    }

    // 交换container.lows上的i j
    const ti = container.lows[i - 1][image['j']]['i'];
    container.lows[i - 1][image['j']]['i'] = container.lows[i][image['j']]['i']
    container.lows[i][image['j']]['i'] = ti;
    const tj = container.lows[i - 1][image['j']]['j'];
    container.lows[i - 1][image['j']]['j'] = container.lows[i][image['j']]['j']
    container.lows[i][image['j']]['j'] = tj;

    // 交换image数组位置
    const tl = container.lows[i - 1][image['j']]
    const te = container.els[i - 1][image['j']]

    container.lows[i - 1][image['j']] = container.lows[i][image['j']]
    container.els[i - 1][image['j']] = container.els[i][image['j']];

    container.lows[i][image['j']] = tl
    container.els[i][image['j']] = te
  }
}

/**
 * 查找point点位置所在的矩形
 * @param container
 * @param {{x:number, y:number}} point
 * @return {{rect:Phaser.GameObjects.Image, piece:Phaser.GameObjects.Image}|null}
 */
const findRect = (container, point) => {
  const low = container.lows.flat(1).find(image => {
    const {x, y, displayWidth: width, displayHeight: height} = image;

    return isInRect(point, {x: x - width / 2, y: y - height / 2, width, height})
  })

  return low ? {rect: low, piece: container.els[low['i']][low['j']]} : null;
}

/**
 * 选择框激活，激活成功游戏进度加一
 * @param {{checkboxes: Phaser.GameObjects.Image[], lows: [][], els: [][]}} container
 * @param {{x:number, y:number}} point
 * @param {number} targetIndex 两次点击的序号
 * @return {boolean} 成功激活返回true
 */
const checkboxActive = (container, point, targetIndex) => {
  // 目标image
  const targetImage = findLow(container, 'lows', targetIndex);

  // 目标image宽高
  const width = targetImage.displayWidth;
  const height = targetImage.displayHeight;
  // 目标矩形
  const target = {
    x: targetImage.x - width / 2,
    y: targetImage.y - height / 2,
    width: targetImage.displayWidth,
    height: targetImage.displayHeight
  };

  // point在矩形内则选中
  if (isInRect(point, target)) {
    // 拿到矩形选中框
    const checkbox = container.checkboxes[targetIndex];
    checkbox.x = targetImage.x;
    checkbox.y = targetImage.y;
    // 显示checkbox
    checkbox.visible = true;
    return true;
  }
  return false;
}

/**
 * 连接两个选中矩形
 * @param {Phaser.Scene} that
 * @param {Phaser.GameObjects.Image} pre 上一次选择的矩形
 * @param {Phaser.GameObjects.Image} cur 本次选择的矩形
 * @return {[]|null}
 */
const linkPiece = (that, pre, cur) => {
  if (pre === null || cur === null) {
    return null;
  }

  const pi = pre['i'];
  const pj = pre['j'];
  const ci = cur['i'];
  const cj = cur['j'];

  // 两个点类型不同
  if (proportion <= 0.76) {
    if (colLayout[pi + 1][pj + 1] !== colLayout[ci + 1][cj + 1]) return null;
  } else {
    if (rowLayout[pi + 1][pj + 1] !== rowLayout[ci + 1][cj + 1]) return null;
  }

  // 找两个image在棋盘对应下标
  const prePoint = {x: pi + 1, y: pj + 1}
  const curPoint = {x: ci + 1, y: cj + 1}

  /**
   * 连通算法，获取连接路径：link表示连接的折点
   * @type {[]} null表示无法连接
   */
  return LinkSearch.connection(proportion <= 0.76 ? colLayout : rowLayout, prePoint, curPoint);
}

/**
 * 创建连接线
 * @param {Phaser.Scene} that
 * @param {Phaser.GameObjects.Image} pre
 * @param {Phaser.GameObjects.Image} cur
 * @param {[{x:number, y:number}]} link
 */
const createLink = (that, pre, cur, link) => {
  const pen = that.add.graphics();
  const width = pre.displayWidth * 0.3;
  pen.alpha = 0;
  pen.fillStyle(0xffdd00, 1);
  pen.lineStyle(pre.displayWidth * 0.2, 0xffdd00, 1);

  switch (link.length) {
    case 0:
      // 连接线
      createLine(that, pre, cur, width)
      break;
    case 1:
      // 中间点
      const mid = link[0].x - 1 === pre['i']
        ? {x: cur.x, y: pre.y}
        : {x: pre.x, y: cur.y}
      createLine(that, pre, mid, width);
      createLine(that, mid, cur, width);
      break;
    case 2:
      let mid1 = {};
      let mid2 = {};

      if (link[0].x - 1 === pre['i']) {
        // 竖向
        mid1.y = pre.y;
        mid2.y = cur.y;

        // 计算x坐标
        const x = pre.x + pre.displayWidth * (link[0].y - 1 - pre['j']);
        mid1.x = mid2.x = x;
      } else {
        // 横向
        mid1.x = pre.x;
        mid2.x = cur.x;

        const y = pre.y + pre.displayWidth * (link[0].x - 1 - pre['i'])
        mid1.y = mid2.y = y;
      }


      // 左边缘
      if (link[0].y === 0 || link[1].y === 0) {
        mid1.x += pre.displayWidth / 3;
        mid2.x += pre.displayWidth / 3;
      }

      // 上边缘
      if (link[0].x === 0 || link[1].x === 0) {
        mid1.y += pre.displayWidth / 3;
        mid2.y += pre.displayWidth / 3;
      }

      const right = proportion <= 0.76 ? 6 : 11;
      const bottom = proportion <= 0.76 ? 9 : 6;

      // 右边缘
      if (link[0].y === right || link[1].y === right) {
        mid1.x -= pre.displayWidth / 3;
        mid2.x -= pre.displayWidth / 3;
      }

      // 下边缘
      if (link[0].x === bottom || link[1].x === bottom) {
        mid1.y -= pre.displayWidth / 3;
        mid2.y -= pre.displayWidth / 3;
      }

      createLine(that, pre, mid1, width);
      createLine(that, mid1, mid2, width);
      createLine(that, mid2, cur, width);
  }
}

/**
 * 创建连接线
 * @param {Phaser.Scene} that
 * @param {{x:number, y:number}} start
 * @param {{x:number, y:number}} target
 * @param {number} width
 */
const createLine = (that, start, target, width) => {
  // 创建线条
  const midX = (start.x + target.x) * 0.5;
  const midY = (start.y + target.y) * 0.5;
  const line = that.add.image(midX, midY, 'line');
  let flower1, flower2;
  line.displayWidth = width
  line.alpha = 0;

  // 判断方向
  if (start.y === target.y) {
    // 横向
    line.rotation = Math.PI * 0.5;
    line.displayHeight = Math.abs(start.x - target.x);
    flower1 = that.add.image(midX - line.displayHeight / 2, midY, 'flower');
    flower2 = that.add.image(midX + line.displayHeight / 2, midY, 'flower');
  } else {
    // 竖向
    line.displayHeight = Math.abs(start.y - target.y);
    flower1 = that.add.image(midX, midY - line.displayHeight / 2, 'flower');
    flower2 = that.add.image(midX, midY + line.displayHeight / 2, 'flower');
  }
  flower1.scale = flower2.scale = width * 2 / flower1.displayWidth;
  flower1.alpha = 0;
  flower2.alpha = 0;

  // 消除
  that.tweens.add({
    targets: [line, flower1, flower2],
    alpha: 1,
    duration: 300,
    yoyo: 200,
    ease: Phaser.Math.Easing.Sine.InOut,
    onComplete: () => line.destroy()
  })
}

/**
 * 隐藏选中框
 * @param that
 * @param container
 */
const checkboxHidden = (that, container) => {
  setTimeout(() => {
    container.checkboxes.forEach(checkbox => checkbox.visible = false)
  }, 200);
}

/**
 * 消除两个连接的棋子
 * @param {Phaser.Scene} that
 * @param {Phaser.GameObjects.Image} preRect 棋子底部圆角矩形
 * @param {Phaser.GameObjects.Image} curRect
 * @param {Phaser.GameObjects.Image} prePiece 棋子
 * @param {Phaser.GameObjects.Image} curPiece
 * @param {function} callback
 */
const pieceDestroy = (that, preRect, curRect, prePiece, curPiece, callback) => {
  that.tweens.add({
    targets: [preRect, curRect, prePiece, curPiece],
    scale: 0,
    delay: 300,
    duration: 400,
    ease: Phaser.Math.Easing.Sine.InOut,
    onComplete: () => callback()
  })
}

/**
 * 点是否在矩形内
 * @param {{x:number, y:number}} point
 * @param {{x, y, width, height}} rect
 * @return {boolean|boolean}
 */
const isInRect = (point, rect) => {
  return point.x >= rect.x
    && point.x <= rect.x + rect.width
    && point.y >= rect.y
    && point.y <= rect.y + rect.height
}

/**
 * 进入结束页面
 * @param {Phaser.Scene} that
 */
const gameOver = that => {
  that.input.removeAllListeners(Phaser.Input.Events.POINTER_UP)

  // 页面清空，进入动画
  that.tweens.add({
    targets: topText,
    alpha: 0,
    duration: 300,
    ease: Phaser.Math.Easing.Sine.InOut,
    onComplete() {
      topText.destroy();
      const icon = createIcon(that);
      createLogo(that, icon);
      const download = createDownload(that, icon);
      that.input.on(Phaser.Input.Events.POINTER_UP, installHandle, download)

      downloadAnimation(that, download)
    }
  })
}

/**
 * 下载按钮事件
 * @param e
 */
const installHandle = function (e) {
  const {downX, downY} = e
  const {x, y, displayHeight: height, displayWidth: width} = this;

  const rect = {x: x - width / 2, y: y - height / 2, width, height}

  if (isInRect({x: downX, y: downY}, rect)) {
    clickAudio.play();

    install()
  }
}

const install = () => {
  let iosLink = "https://itunes.apple.com/app/id1502227743";
  let androidLink = "https://play.google.com/store/apps/details?id=bp.free.puzzle.game.mahjong.onet";
  let u = navigator.userAgent;
  let app = navigator.appVersion;
  let ios = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
  let iPad = u.indexOf('iPad') > -1;
  let iPhone = u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1;
  if (ios || iPad || iPhone) {
    mraid.openStore(iosLink);
  }
  if (u.indexOf('Android') > -1 || u.indexOf('Adr') > -1) {
    mraid.openStore(androidLink);
  }
}

/**
 * 创建icon
 * @param {Phaser.Scene} that
 * @return {Phaser.GameObjects.Image}
 */
const createIcon = that => {
  const icon = that.add.image(config.width / 2, config.height / 2, 'icon');

  icon.scale = Math.min(config.width * 0.5 / icon.displayWidth, config.height * 0.3 / icon.displayHeight)

  return icon
}

/**
 * 创建logo
 * @param {Phaser.Scene} that
 * @param {Phaser.GameObjects.Image} icon
 * @return {Phaser.GameObjects.Image}
 */
const createLogo = (that, icon) => {
  const logo = that.add.image(config.width / 2, config.height / 2, 'logo')
  logo.scale = icon.scale;
  logo.y = icon.y - logo.displayHeight

  return logo;
}

/**
 * 创建下载按钮
 * @param {Phaser.Scene} that
 * @param {Phaser.GameObjects.Image} icon
 * @return {Phaser.GameObjects.Image}
 */
const createDownload = (that, icon) => {
  const download = that.add.image(config.width / 2, config.height / 2, 'download');
  download.scale = icon.scale * 0.6;
  download.y = icon.y + download.displayHeight * 1.7

  return download;
}

/**
 * 下载按钮动画
 * @param {Phaser.Scene} that
 * @param {Phaser.GameObjects.Image} download
 */
const downloadAnimation = (that, download) => {
  that.tweens.add({
    targets: download,
    scale: download.scale + 0.05,
    duration: 1000,
    ease: Phaser.Math.Easing.Sine.InOut,
    yoyo: true,
    loop: -1
  })
}
